package com.foxchen.ddns.service.impl;

import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.alidns20150109.AsyncClient;
import com.aliyun.sdk.service.alidns20150109.models.*;
import com.foxchen.ddns.config.AliConfig;
import com.foxchen.ddns.config.DDNSConfig;
import com.foxchen.ddns.service.DomainUpdateDnsService;
import com.google.gson.Gson;
import darabonba.core.client.ClientOverrideConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service("ali")
public class AliUpdateServiceImpl extends DomainUpdateDnsServiceAbs implements DomainUpdateDnsService {
    @Resource
    private AliConfig aliConfig;
    @Resource
    private IpGetService ipGetService;

    @Override
    @SuppressWarnings("all")
    public void updateDnsSafe(String domain, DDNSConfig.Detail detail) throws Exception {
        // 获取当前公网ip
        log.info(">>================ddns check and update begin================>>");
        String localPublicIp = ipGetService.getLocalPublicIp(detail);
        String type = detail.getType().equals("v4") ? "A" : "AAAA";

        StaticCredentialProvider provider = StaticCredentialProvider.create(Credential.builder()
                .accessKeyId(aliConfig.getAccessKey())
                .accessKeySecret(aliConfig.getSecretKey())
                .build());

        ClientOverrideConfiguration clientOverrideConfiguration = ClientOverrideConfiguration
                .create()
                .setEndpointOverride("alidns.cn-shanghai.aliyuncs.com")
                .setConnectTimeout(Duration.ofSeconds(30));

        try(AsyncClient client = AsyncClient.builder()
                .region("cn-shanghai")
                .credentialsProvider(provider)
                .overrideConfiguration(clientOverrideConfiguration)
                .build()){

            // 查询原来的解析记录,根据主机记录分组Map
            DescribeDomainRecordsRequest describeDomainRecordsRequest = DescribeDomainRecordsRequest.builder().domainName(domain).build();
            DescribeDomainRecordsResponse domainRecordsResponse = client.describeDomainRecords(describeDomainRecordsRequest).get();
            List<DescribeDomainRecordsResponseBody.Record> recordList = domainRecordsResponse.getBody().getDomainRecords().getRecord();
            Map<String, DescribeDomainRecordsResponseBody.Record> rrMap = recordList.stream().collect(Collectors.toMap(DescribeDomainRecordsResponseBody.Record::getRr, Function.identity(), (k1, k2) -> k2));

            // 便利现在的配置，如果有,判断解析值和当前是否相同，不相同则修改，没有就新增
            for (String rr : detail.getAnalysis()) {
                if(rrMap.containsKey(rr)){
                    DescribeDomainRecordsResponseBody.Record oldRecord = rrMap.get(rr);
                    if(oldRecord.getValue().equals(localPublicIp)){
                        log.info("old info not need update,domain={},rr={},value={}",oldRecord.getDomainName(),oldRecord.getRr(),oldRecord.getValue());
                        continue;
                    }
                    UpdateDomainRecordRequest updateDomainRecordRequest = UpdateDomainRecordRequest.builder()
                            .recordId(oldRecord.getRecordId())
                            .rr(rr)
                            .type(type)
                            .value(localPublicIp)
                            .build();
                    UpdateDomainRecordResponse updateDomainRecordResponse = client.updateDomainRecord(updateDomainRecordRequest).get();
                    log.info("update old record,domain={},rr={},response => {}",domain,rr,new Gson().toJson(updateDomainRecordResponse));
                } else {
                    AddDomainRecordRequest addDomainRecordRequest = AddDomainRecordRequest.builder()
                            .domainName(domain)
                            .rr(rr)
                            .type(type)
                            .value(localPublicIp)
                            .build();
                    AddDomainRecordResponse resp = client.addDomainRecord(addDomainRecordRequest).get();
                    log.info("add new record,domain={},rr={},response => {}",domain,rr,new Gson().toJson(resp));
                }
            }
            client.close();
        }
        log.info("<<================ddns check and update end================<<");
    }
}
